﻿using System;
using YasharEl.Infrastructure.EntityModel;
using NHibernate;
using NHCfg = NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using YasharEl.Infrastructure.ObjectFactory;
using System.Diagnostics.Contracts;

namespace YasharEl.Infrastructure.PersistenceModel.NHibernate
{
	public class NHibernateUnitOfWorkFactory : IUnitOfWorkFactory
    {
        #region Constructors

        public NHibernateUnitOfWorkFactory(
            IDependencyResolver resolver, string connectionStringName, string settingsFile)
        {
            Contract.Requires<ArgumentNullException>(resolver != null, "resolver could not be null.");

            IPersistenceModelConfigurationBuilder<NHCfg.Configuration> configurationBuilder = resolver.Resolve<IPersistenceModelConfigurationBuilder<NHCfg.Configuration>>();
            configurationBuilder.BuildConfiguration(resolver, settingsFile, connectionStringName);

            Configuration = configurationBuilder.GetConfiguration();
            SessionFactory = Configuration.BuildSessionFactory();
        }

        #endregion

        #region Protected Properties

        protected ISessionFactory SessionFactory { get; private set; }

        protected NHCfg.Configuration Configuration { get; private set; }

        #endregion

        #region Public Methods

        /// <summary>
		/// Generates table structure inside specified database.
		/// </summary>
		public void NHibernateSchemaExport()
		{
			new SchemaExport(this.Configuration).Execute(false, true, false);
		}

        #endregion

        #region IUnitOfWorkFactory Members

        public IUnitOfWork BeginUnitOfWork()
		{
			return new NHibernateUnitOfWork( this.SessionFactory.OpenSession() );
		}

		public void EndUnitOfWork(IUnitOfWork unitOfWork)
		{
			var nhUnitOfWork = unitOfWork as NHibernateUnitOfWork;
			if ( unitOfWork != null )
			{
				unitOfWork.Dispose();
				unitOfWork = null;
			}
		}

		#endregion

		#region IDisposable Members

		public void Dispose()
		{
			if ( this.SessionFactory != null )
			{
				(this.SessionFactory as IDisposable).Dispose();
				this.SessionFactory = null;
				this.Configuration = null;
			}
		}

		#endregion
	}
}
